﻿using Autofac;
using Cordyceps.Micro.Core.Dependencys;
using Microsoft.Extensions.DependencyInjection;
using System.Reflection;
using Module = Autofac.Module;

namespace Cordyceps.Micro.Core
{
    public class CordycepsModule : Module
    {
        protected override void Load(ContainerBuilder builder)
        {
            var entryAssembly = Assembly.GetEntryAssembly() ?? throw new InvalidOperationException("Entry assembly not found.");

            // 推断业务程序集（可根据需要扩展）
            var applicationAssembly = TryLoadAssembly(entryAssembly, ".Application");
            var contractsAssembly = TryLoadAssembly(entryAssembly, ".Application.Contracts");
            var domainAssembly = TryLoadAssembly(entryAssembly, ".Domain");
            var efAssembly = TryLoadAssembly(entryAssembly, ".EntityFrameworkCore");

            var assembliesToScan = new List<Assembly>();
            if (applicationAssembly != null) assembliesToScan.Add(applicationAssembly);
            if (contractsAssembly != null) assembliesToScan.Add(contractsAssembly);
            // 自动注册所有实现 ITransientDependency 的类型
            RegisterByDependencyInterface(builder, assembliesToScan, typeof(ITransientDependency), ServiceLifetime.Transient);

            ConfigureContainer(builder);
        }

        /// <summary>
        /// 子类可重写以添加自定义注册
        /// </summary>
        protected virtual void ConfigureContainer(ContainerBuilder builder) { }

        private static void RegisterByDependencyInterface(
            ContainerBuilder builder,
            IEnumerable<Assembly> assemblies,
            Type markerInterface,
            ServiceLifetime scope)
        {
            var types = assemblies
                .SelectMany(a => a.GetTypes())
                .Where(t => t.IsClass && !t.IsAbstract && !t.IsGenericTypeDefinition)
                .Where(t => markerInterface.IsAssignableFrom(t));

            foreach (var type in types)
            {
                // 获取该类型实现的所有“非标记”接口（排除 ITransientDependency 等）
                var serviceInterfaces = type.GetInterfaces()
                    .Where(i => i != markerInterface
                             && i != typeof(IScopedDependency)
                             && i != typeof(ISingletonDependency)
                             && !i.Assembly.FullName?.StartsWith("Microsoft") == true
                             && !i.Assembly.FullName?.StartsWith("System") == true)
                    .ToArray();

                if (serviceInterfaces.Length == 0)
                {
                    // 如果没有业务接口，也可以 self-bind（可选）
                    RegisterByScope(builder, type, type, scope);
                }
                else
                {
                    foreach (var iface in serviceInterfaces)
                    {
                        RegisterByScope(builder, type, iface, scope);
                    }
                }
            }
        }


        private static void RegisterByScope(ContainerBuilder builder, Type implType, Type serviceType, ServiceLifetime scope)
        {
            var reg = builder.RegisterType(implType).As(serviceType);
            _ = scope switch
            {
                ServiceLifetime.Transient => reg.InstancePerDependency(),
                ServiceLifetime.Scoped => reg.InstancePerLifetimeScope(),
                ServiceLifetime.Singleton => reg.SingleInstance(),
                _ => throw new ArgumentOutOfRangeException(nameof(scope), scope, null)
            };
        }

        private static Assembly? TryLoadAssembly(Assembly reference, string suffix)
        {
            var name = reference.GetName().Name;
            if (string.IsNullOrEmpty(name)) return null;

            var targetName = name.Replace(".HttpHost", suffix)
                                 .Replace(".HttpApi", suffix);

            try
            {
                return Assembly.Load(new AssemblyName(targetName));
            }
            catch
            {
                return null;
            }
        }
    }
}
